#include "common.h"


Node* nodes=NULL;//节点信息
Rack* racks=NULL;//机架信息

int gateway_AsClient_sockfd[NodeNumTotal-1]={-1};
int gateway_AsServer_sockfd[NodeNumTotal-1]={-1};
int isDestory=0;
int count=0; //发送次数
long long netcoretraffic=0;

int init_gateway();
int worker2gateway_recv(Worker2WorkerRequest* request,int sockfd);
int handlerIOFromWorker(int gateway_AsServer_fd);
void destroy_gateway();
void gateway2worker_send(Worker2WorkerRequest* request);
void* process4worker_thread(void* arg);

//作为中转服务器使用
int main(int argc, char const *argv[])
{
	init_gateway();
	printf("gate recv count:%d,total traffic:%lld\n",count,netcoretraffic);
	pthread_t thread4worker_ID[NodeNumTotal-1];
	for (int i = 0; i < NodeNumTotal-1; ++i)
	{
		pthread_create(&thread4worker_ID[i],NULL,process4worker_thread,(void*)gateway_AsServer_sockfd[i]);
	}

	while(1){
		if(isDestory==1){
			break;
		}
	}

	for (int i = 0; i < NodeNumTotal-1; ++i)
	{
		pthread_cancel(thread4worker_ID[i]);
	}
	destroy_gateway();
	return 0;
}

void* process4worker_thread(void* arg){
	int sockfd = (int)arg;
	int isfinish=0;
	while(isfinish==0){
		int ret = handlerIOFromWorker(sockfd);
		if (ret==ERR)
		{
			isfinish=1;
		}
	}
	printf("process4worker_thread has end\n");
	return NULL;
}

void destroy_gateway(){
	if (nodes!=NULL) free(nodes);
	if (racks!=NULL) free(racks);
	for (int i = 0; i < NodeNumTotal-1; ++i) close(gateway_AsClient_sockfd[i]);
	for (int i = 0; i < NodeNumTotal-1; ++i) close(gateway_AsServer_sockfd[i]);
}

int worker2gateway_recv(Worker2WorkerRequest* request,int sockfd){
	size_t needRecv =sizeof(Worker2WorkerRequest);
	char *recvBuf=(char *)malloc(needRecv);
	int len = recv_bytes(sockfd,recvBuf,needRecv);
	memcpy(request,recvBuf,needRecv);  //反序列化
	free(recvBuf);
	return len;
}

void gateway2worker_send(Worker2WorkerRequest* request){
	size_t needSend=sizeof(Worker2WorkerRequest);
	char *sendBuf=(char *)malloc(needSend);
	memcpy(sendBuf,request,needSend); //序列化
	send_bytes(gateway_AsClient_sockfd[request->toNodeID],sendBuf,needSend); //Client发送请求至worker
	if (sendBuf!=NULL) free(sendBuf);
}

int handlerIOFromWorker(int gateway_AsServer_fd){
	Worker2WorkerRequest* request = (Worker2WorkerRequest*)malloc(sizeof(Worker2WorkerRequest));
	int len = worker2gateway_recv(request,gateway_AsServer_fd);
	netcoretraffic=netcoretraffic+sizeof(Worker2WorkerRequest);
	printf("gate recv count:%d,total traffic:%lld\n",++count,netcoretraffic);
	if (len<=0)
	{
		printf("recv the incorrect request len:%d\n",len);
		return ERR;
	}
	printf("gateway starts to redirect worker2workerrequest from worker[%d] to worker[%d]\n",request->fromNodeID,request->toNodeID);

	gateway2worker_send(request);
	printf("has redirect to NodeID[%d]\n",request->toNodeID);

	if (request->flag==1)
	{
		printf("cross_rack write request blockID:%lld\n", request->blockID);
		//再次接受来自fromNode的blockdata
		char* recvBuf = (char*)malloc(sizeof(char)*Block_Size);
		recv_bytes(gateway_AsServer_fd,recvBuf,Block_Size);
		//然后转发给tonodeid
		send_bytes(gateway_AsClient_sockfd[request->toNodeID],recvBuf,Block_Size);
		free(recvBuf);
		printf("gateway server success redirect the blockdata to toNodeID:%d\n",request->toNodeID);
		//再次接受来自toNodeID的requestID
		long requestID4Check;
		recv_bytes(gateway_AsClient_sockfd[request->toNodeID],(char*)&requestID4Check,sizeof(long));
		//转发给fromNodeID
		send_bytes(gateway_AsServer_fd,(char*)&requestID4Check,sizeof(long));
		printf("gateway server success redirect the requestID4Check to fromNodeID:%d\n",request->fromNodeID);
		netcoretraffic=netcoretraffic+sizeof(long)+Block_Size;
		printf("gate recv count:%d,total traffic:%lld\n",++count,netcoretraffic);
	}else if (request->flag==0)
	{
		printf("cross_rack read request blockID:%lld\n", request->blockID);
		//接受来自toNodeID的blockdata
		char* recvBuf = (char*)malloc(sizeof(char)*Block_Size);
		recv_bytes(gateway_AsClient_sockfd[request->toNodeID],recvBuf,Block_Size);
		//转发给fromNodeID
		send_bytes(gateway_AsServer_fd,recvBuf,Block_Size);
		free(recvBuf);
		printf("gateway server success redirect the blockdata to fromNodeID:%d\n",request->fromNodeID);
		//再次接受来自toNodeID的requestID
		long requestID4Check;
		recv_bytes(gateway_AsClient_sockfd[request->toNodeID],(char*)&requestID4Check,sizeof(long));
		//转发给fromNodeID
		send_bytes(gateway_AsServer_fd,(char*)&requestID4Check,sizeof(long));
		printf("gateway server success redirect the requestID4Check to fromNodeID:%d\n",request->fromNodeID);
		netcoretraffic=netcoretraffic+sizeof(long)+Block_Size;
		printf("gate recv count:%d,total traffic:%lld\n",++count,netcoretraffic);
	}else if (request->flag==2)
	{
		printf("cross_rack del request blockID:%lld\n", request->blockID);
		//再次接受来自toNodeID的requestID
		long requestID4Check;
		recv_bytes(gateway_AsClient_sockfd[request->toNodeID],(char*)&requestID4Check,sizeof(long));
		//转发给fromNodeID
		send_bytes(gateway_AsServer_fd,(char*)&requestID4Check,sizeof(long));
		printf("gateway server success redirect the requestID4Check to fromNodeID:%d\n",request->fromNodeID);
		netcoretraffic=netcoretraffic+sizeof(long);
		printf("gate recv count:%d,total traffic:%lld\n",++count,netcoretraffic);
	}else{
		printf("recv the incorrect Worker2WorkerRequest\n");
		free(request);
		return ERR;
	}
	free(request);
	printf("gateway successfully finish a worker2workerrequest redirect process\n");
	return 0;
}


int init_gateway(){
	printf("init_gateway() starting.......................\n");

	if (set_server_limit() <0) {
      	printf("init_master()====set_server_limit error\n");
		return ERR;
    }
    //初始化配置文件
	nodes=read_config_Node(CONFIG_NODE);
	printf("read_config_Node end............................\n");
	racks=read_config_Rack(CONFIG_RACK);
	printf("read_config_Rack end............................\n");

	//初始化每个worker的连接以及每个worker的监听
	for (int i = 0; i < NodeNumTotal-1; ++i)
	{
		gateway_AsServer_sockfd[i]=server_accept(Worker2GateWayPort+i,Max_Length_backlog);
		if (gateway_AsServer_sockfd[i]!=-1)
		{
			printf("gateway_init()======success to server_accept nodeID[%d] gateway_AsServer_sockfd=%d\n",i,gateway_AsServer_sockfd[i]);	
		}else{
			printf("gateway_init()======fail to server_accept nodeID[%d]\n",i);
			return ERR;
		}
	}

	for (int i = 0; i < NodeNumTotal-1; ++i)
	{
		gateway_AsClient_sockfd[i]=connect_try(nodes[i].ip,GateWay2WorkerPort);
		if (gateway_AsServer_sockfd[i]!=-1)
		{
			printf("gateway_init()======success to connect to nodeID[%d] gateway_AsClient_sockfd=%d\n",i,gateway_AsClient_sockfd[i]);
		}else{
			printf("gateway_init()======fail to connect to nodeID[%d]\n",i);
			return ERR;
		}	
	}
	printf("init_gateway() successfully end.......................\n");
}